﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Web.Caching;
using Medianamik.Core;
using Medianamik.Core.Caching;
using Medianamik.Core.DAL;
using Medianamik.Core.DAL.Repositories;
using Medianamik.Core.DAL.Services;
using Medianamik.UI.Web.Shop.Data.Dto;
using SubSonic;
using System.Linq;

namespace Medianamik.UI.Web.Shop.Data.Repositories
{
    public class CategoryRepository<TCollection, TItem> : MedianamikRepository<TCollection, TItem>, ICategoryRepository<TItem>
        where TItem : Interfaces.ICategory, IRecordBase, new()
        where TCollection : ICollectionWithChildren<TCollection, TItem>, new()
    {
        private readonly ICacheService<TItem> _cacheService;

        public CategoryRepository(ICultureService cultureService, IContentStateService contentStateService, INodeMapper nodeMapper, ICacheService<TItem> cacheService)
            : base(cultureService, contentStateService, nodeMapper)
        {
            _cacheService = cacheService;
        }

        public IList<ProductCategoryManyToManyDto> GetProductCategoriesWithParent()
        {
            return GetProductCategoriesWithParent(CultureInfo.CurrentCulture, ContentState.Draft, ActiveStatus.All);
        }

        public IList<ProductCategoryManyToManyDto> GetProductCategoriesWithParent(CultureInfo culture, ContentState contentState, ActiveStatus status)
        {
            var categories = All(culture, contentState, status);
            IList<ProductCategoryManyToManyDto> productCategorieManyToManyDto = new List<ProductCategoryManyToManyDto>();
            int level = 0;

            foreach (var category in categories)
            {
                productCategorieManyToManyDto.Add(new ProductCategoryManyToManyDto
                {
                    Name = GetCategoryNameWithParent(category.ParentNodeId.Value, ref level, ref categories) + category.Name,
                    NodeId = category.NodeId,
                    TypeId = category.TypeId
                });
            }

            productCategorieManyToManyDto = productCategorieManyToManyDto.OrderBy(cat => cat.Name).ToList();

            return productCategorieManyToManyDto;
        }

        public virtual string GetCategoryNameWithParent(Guid categoryId, ref int level, ref IList<TItem> categories)
        {
            const string separator = " \\ ";
            string result;


            if (categoryId == PageIds.CategoryList) //"317E6ABA-8454-4A52-9688-D76C17739570")
            {
                level = 0;
                return "";
            }
            var selectedCategory = categories.Where(cat => cat.NodeId == categoryId).FirstOrDefault();

            if (selectedCategory == null)
            {
                return "";
            }
            var parentCategoryName = GetCategoryNameWithParent(selectedCategory.ParentNodeId.Value, ref level,
                                                               ref categories);

            level += 1;

            if (!parentCategoryName.IsNullOrEmpty())
            {
                if (level == 2)
                {
                    return String.Format("{0}{1}{2}", parentCategoryName, selectedCategory.Name, separator);
                }
                return String.Format("{0}{1}{2}{3}", parentCategoryName, separator, selectedCategory.Name,
                                     separator);
            }
            return String.Format("{0}{1}", selectedCategory.Name, separator);
        }
    }

    public class CategoryRepository : CategoryRepository<CategoryCollection,
        Category>, ICategoryRepository
    {

        public CategoryRepository(ICultureService cultureService, IContentStateService contentStateService, INodeMapper nodeMapper, ICacheService<Category> cacheService)
            : base(cultureService, contentStateService, nodeMapper, cacheService)
        {

        }
    }

    public interface ICategoryRepository<T> : IMedianamikRepository<T>
    where T : Interfaces.ICategory
    {
        IList<ProductCategoryManyToManyDto> GetProductCategoriesWithParent();
        IList<ProductCategoryManyToManyDto> GetProductCategoriesWithParent(CultureInfo culture, ContentState contentState,
            ActiveStatus status);
        string GetCategoryNameWithParent(Guid categoryId, ref int level, ref IList<T> categories);
    }

    public interface ICategoryRepository :ICategoryRepository<Category>
    {}
}
